package com.joey.concurrency.example.lock;

import java.util.concurrent.locks.StampedLock;

/**
 * @Author hyy
 **/
public class StampedLockExample {
    //内部定义表示坐标
    private double x,y;
    //定义StampedLock
    private final StampedLock stampedLock = new StampedLock();

    void move(double inputX,double inputY){
        //这里的含义何distanceFormOrigin方法中，stampedLock.readLock一致
        long stamp = stampedLock.writeLock();
        try{
            x += inputX;
            y += inputY;
        } finally {
            stampedLock.unlockWrite(stamp);
        }
    }
    //只读方法
    double distanceFormOrigin(){
        //试图尝试一次乐观读 返回一个类似于时间戳的邮戳整数stamp 这个stamp就可以作为这一个所获取的凭证
        long stamp = stampedLock.tryOptimisticRead();
        //读取x和y的值,这时候我们并不确定x和y是否是一致的
        double currentX = x,currentY = y;
        /**
         * 判断这个stamp是否在读过程发生期间被修改过,如果stamp没有被修改过,责任无这次读取时有效的,
         * 因此就可以直接return了,反之,如果stamp是不可用的,则意味着在读取的过程中,
         * 可能被其他线程改写了数据,因此,有可能出现脏读,如果如果出现这种情况,
         * 我们可以像CAS操作那样在一个死循环中一直使用乐观锁,知道成功为止!!!!!!
         */
        if(!stampedLock.validate(stamp)){
            //也可以升级锁的级别,这里我们升级乐观锁的级别,将乐观锁变为悲观锁, 如果当前对象正在被修改,则读锁的申请可能导致线程挂起.
            stamp = stampedLock.readLock();

            try{
                currentX = x;
                currentY = y;
            }finally {
                //退出临界区,释放读锁
                stampedLock.unlockRead(stamp);
            }
        }
        return Math.sqrt(currentX * currentX + currentY * currentY);
    }
}
